package com.chuhe.common.serviceutil;

import com.chuhe.common.exception.BusinessException;
import com.chuhe.common.exception.CommonErrorEnum;
import lombok.SneakyThrows;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * 分布式锁 工具API
 * @Author: 楚河
 * @Date: 2025年05月12日15:17
 */
@Service
public class LockService {
    @Autowired
    private RedissonClient redissonClient;

    @SneakyThrows
    public <T> T executeWithLock(String key, int waitTime, TimeUnit timeUnit, Supplier<T> supplier) {
        //获取锁
        RLock lock = redissonClient.getLock(key);
        //尝试解锁
        boolean success = lock.tryLock(waitTime, timeUnit);
        if(!success){
            throw new BusinessException(CommonErrorEnum.CODE_901);
        }
        try {
            return supplier.get();
        }finally {
            lock.unlock();
        }
    }

    /**
     * （waitTime = 0）
     * 尝试立即获取锁（不等待），失败直接抛异常，成功则执行业务逻辑并自动释放锁.
     * 锁持有期间默认通过看门狗机制自动续期（默认30秒）.
     */
    public <T> T executeWithLock(String key, Supplier<T> supplier) {
        return executeWithLock(key, 0, TimeUnit.MILLISECONDS, supplier);
    }
    /**
     * （waitTime = -1）
     * 无限等待获取锁（可能造成死锁）
     * @Author: 楚河
     * @Date: 2025-05-14 14:02
     */
    public <T> T executeWithLock(String key, Runnable runnable) {
        return executeWithLock(key, -1, TimeUnit.MILLISECONDS, ()->{
            runnable.run();
            return null;
        });
    }
}
